home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJ111M1.ZIP / go32 / control.c < prev    next >
C/C++ Source or Header  |  1993-12-17  |  30KB  |  1,169 lines

  1. /* This is file CONTROL.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  16. /* Modified for DPMI Implement by H.Tsubakimoto */
  17. /* Merged DPMI and V1.09 C. Sandmann sandmann@clio.rice.edu */
  18.  
  19. #include <dos.h>
  20. #include <dir.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <fcntl.h>
  24. #include <sys/stat.h>
  25. #include <string.h>
  26. #include <ctype.h>
  27. #include <io.h>
  28.  
  29. #include "gotypes.h"
  30. #include "gdt.h"
  31. #include "idt.h"
  32. #include "tss.h"
  33. #include "valloc.h"
  34. #include "utils.h"
  35. #include "graphics.h"
  36. #include "mono.h"
  37. #include "vcpi.h"
  38. #include "paging.h"
  39. #include "dpmi.h"
  40. #include "extdebug.h"
  41. #include "exphdlr.h"
  42. #include "dalloc.h"
  43. #include "vcpi.h"
  44. #include "mswitch.h"
  45. #include "xms.h"
  46. #include "npx.h"
  47. #include "stubinfo.h"
  48. #include "proginfo.h"
  49. #include "control.h"
  50. #include "eventque.h"
  51.  
  52. /* stamp.c will find this and replace it with the correct timestamp
  53.    but leave the TIMETIME key alone */
  54. static char build_time[] = "TIMETIMExxx xxx xx xx:xx:xx xxxx";
  55.  
  56. StubInfo stub_info = {
  57.   STUB_INFO_MAGIC,
  58.   sizeof(StubInfo),
  59.   "go32",
  60.   {
  61.     GO32_RELEASE_NUMBER,
  62.     GO32_RELEASE_TYPE_C,
  63.     GO32_MINOR_VERSION,
  64.     GO32_MAJOR_VERSION
  65.   },
  66.   262144L,
  67.   0L,
  68.   "",
  69.   1,
  70.   0L
  71. };
  72.  
  73. PROGINFO prog_info;
  74.  
  75. int topline_info = 0;
  76. int show_memory_info = 0;
  77.  
  78. extern transfer_buffer[];
  79. extern word32 transfer_linear;
  80.  
  81. extern int ctrl_c_flag, in_hardware_interrupt;
  82.  
  83. GDT_S gdt[g_num];
  84. IDT idt[256];
  85.  
  86. TSS *tss_ptr;
  87. int debug_mode = 0;
  88. int self_contained;
  89. long header_offset = 0;
  90. int use_ansi=0;
  91. int use_mono=0;
  92. int redir_1_mono=0;
  93. int redir_2_mono=0;
  94. int redir_2_1=0;
  95. int redir_1_2=0;
  96.  
  97. static int initial_argc;
  98. static int old_video_mode;
  99. static int globbing=-1;
  100. static int old_mask1, old_mask2;
  101.  
  102. int16 ems_handle=0;        /*  Get EMS Handle  */
  103. word16 vcpi_installed = 0;    /*  VCPI Installed Flag  */
  104. char use_DPMI = 0;
  105. extern word32 DPMI_STACK;
  106. word32 ARENA = 0x10000000L;
  107.  
  108. int ctrl_break_hit = 0;
  109.  
  110. extern word32 far *pd;
  111.  
  112. extern void far ivec0(void), ivec1(void);
  113. extern void ivec7(void), ivec75(void);
  114. extern void interrupt_common(void), page_fault(void);
  115. extern void v74_handler(void), v78_handler(void), v79_handler(void);
  116.  
  117. void interrupt (*old_ctrlbrk)();
  118.  
  119. void set_command_line(char **argv, char **envv);
  120.  
  121. int exitDPMI = 0;
  122.  
  123. char *exception_names[] = {
  124.   "Division by Zero",
  125.   "Debug",
  126.   0,
  127.   "Breakpoint",
  128.   "Overflow",
  129.   "Bounds Check",
  130.   "Invalid Opcode",
  131.   "Coprocessor not available",
  132.   "Double Fault",
  133.   "Coprocessor overrun",
  134.   "Invalid TSS",
  135.   "Segment Not Present",
  136.   "Stack Fault",
  137.   "General Protection Fault",
  138.   "Page fault",
  139.   0,
  140.   "Coprocessor Error",
  141.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  142.   "Unsupported DOS request"
  143. };
  144. #define EXCEPTION_COUNT (sizeof(exception_names)/sizeof(exception_names[0]))
  145.  
  146. unsigned int cdecl _openfd[255] = {
  147.   0x6001,0x7002,0x6002,0xa004,0xa002,0xffff,0xffff,0xffff,
  148.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  149.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  150.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  151.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  152.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  153.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  154.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  155.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  156.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  157.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  158.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  159.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  160.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  161.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  162.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  163.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  164.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  165.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  166.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  167.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  168.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  169.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  170.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  171.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  172.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  173.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  174.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  175.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  176.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  177.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  178.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff
  179. };
  180.  
  181. void bump_file_limit(void)
  182. {
  183.   if (((((int)_osmajor)<<8)|_osminor) < 0x0303)
  184.     return;
  185.   _AH = 0x67;
  186.   _BX = 255;
  187.   geninterrupt(0x21);
  188. }
  189.  
  190. void initialize_printer(void)
  191. {
  192.   _BX=4;
  193.   _AH=0x44;
  194.   _AL=0x01;
  195.   _DX=0xa0;
  196.   geninterrupt(0x21);
  197.   setmode(4, O_BINARY);
  198. }
  199.  
  200. void fillgdt(int sel, word32 limit, word32 base, word8 type, int G)
  201. {
  202.   GDT_S *g;
  203.   g = gdt+sel;
  204.   if (G & 2)
  205.     limit = limit >> 12;
  206.   g->lim0 = limit & 0xffff;
  207.   g->lim1 = (limit>>16) & 0x0f;
  208.   g->base0 = base & 0xffff;
  209.   g->base1 = (base>>16) & 0xff;
  210.   g->base2 = (base>>24) & 0xff;
  211.   g->stype = type;
  212.   g->lim1 |= G * 0x40;
  213. }
  214.  
  215. void setup_tss(TSS *t, void (*eip)())
  216. {
  217.   memset(t, 0, sizeof(TSS));
  218.   t->tss_cs = g_rcode*8;
  219.   t->tss_eip = (long)FP_OFF(eip);
  220.   t->tss_ss = g_rdata*8;
  221.   t->tss_esp = (long)FP_OFF(t->tss_stack);
  222.   t->tss_ds = g_rdata*8;
  223.   t->tss_es = g_rdata*8;
  224.   t->tss_fs = g_rdata*8;
  225.   t->tss_eflags = 0x0200;
  226.   t->tss_iomap = 0xffff; /* no map */
  227. }
  228.  
  229. void abort(void);
  230.  
  231. void my_abort()
  232. {
  233.   static int recursing = 0;
  234.   if (recursing)
  235.     _exit(1);
  236.   recursing = 1;
  237.   printf("Abort!\n");
  238.   exit(1);
  239. }
  240.  
  241. void exit_func(void)
  242. {
  243.   int i;
  244.   dalloc_uninit();
  245.   EventQueueDeInit();
  246.   uninit_controllers();
  247.   if(!use_DPMI) {
  248.     valloc_uninit();
  249.     if ((ems_handle)&&(ems_handle != -1))
  250.       ems_free(ems_handle);    /*  Deallocated EMS Page    */
  251.     if (vcpi_installed)
  252.       vcpi_flush();        /*  Deallocated VCPI Pages  */
  253.   } else {
  254.     DPMIprotectedMode();
  255.     clearDPMIstate();
  256.     restoreDPMIvector();
  257.     uninitDPMI(exitDPMI);
  258.   }
  259.   if (topline_info)
  260.     for (i=0; i<80; i++)
  261.       poke(screen_seg, i*2, 0x0720);
  262.   outportb(0x21, old_mask1);
  263.   outportb(0xa1, old_mask2);
  264.   setvect(0x1b, old_ctrlbrk);
  265. }
  266.  
  267. void show_call_frame(void)
  268. {
  269.   word32 vbp,vbp_new, tos;
  270.   int max=0;
  271.  
  272.   if (tss_ptr == &ed_tss)
  273.     tos = 0xb0000000L;
  274.   else
  275.     tos = 0x90000000L;
  276.   vbp = tss_ptr->tss_ebp;
  277.   fprintf(stderr,"Call frame traceback EIPs:\n  0x%08lx\n",tss_ptr->tss_eip);
  278.   if (vbp == 0) return;
  279.   do {
  280.     vbp_new = peek32(vbp+ARENA);
  281.     if (vbp_new == 0) break;
  282.     fprintf(stderr,"  0x%08lx\n",peek32(vbp+ARENA+4));  /* EIP */
  283.     vbp = vbp_new;
  284.     if (++max == 10)
  285.       break;
  286.   } while ((vbp >=tss_ptr->tss_esp) && (vbp < tos));
  287.   /* 0x9000000 = areas[A_stack].last_addr for DPMI, but stack can be moved */
  288. }
  289.  
  290. void do_faulting_finish_message(int print_reason, int exit_code)
  291. {
  292.   if (peekb(0x40, 0x49) != old_video_mode)
  293.   {
  294.     _AX = old_video_mode;
  295.     geninterrupt(0x10);
  296.   }
  297.   if (tss_ptr->tss_irqn == hard_master_lo+1)
  298.   {
  299.     fprintf(stderr, "Ctrl-%s Hit!  Stopped at address %lx\n",
  300.       ctrl_break_hit ? "Break" : "C", tss_ptr->tss_eip);
  301.     if (ctrl_break_hit)
  302.       show_call_frame();
  303.   }
  304.   else
  305.   {
  306.     if (print_reason)
  307.     {
  308.       char *en = (tss_ptr->tss_irqn >= EXCEPTION_COUNT) ? 0 : exception_names[tss_ptr->tss_irqn];
  309.       if (tss_ptr->tss_irqn == hard_slave_lo + 5)
  310.     en = "Floating Point exception";
  311.       if (en == 0)
  312.     fprintf(stderr, "Exception %d (0x%02x) at eip=%lx\n",
  313.         tss_ptr->tss_irqn, tss_ptr->tss_irqn, tss_ptr->tss_eip);
  314.       else
  315.     fprintf(stderr, "%s at eip=%lx\n", en, tss_ptr->tss_eip);
  316.     }
  317.     fprintf(stderr, "eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
  318.        tss_ptr->tss_eax,
  319.        tss_ptr->tss_ebx,
  320.        tss_ptr->tss_ecx,
  321.        tss_ptr->tss_edx,
  322.        tss_ptr->tss_esi,
  323.        tss_ptr->tss_edi);
  324.     fprintf(stderr, "ebp=%08lx esp=%08lx cs=%x ds=%x es=%x fs=%x gs=%x ss=%x cr2=%08x\n",
  325.        tss_ptr->tss_ebp,
  326.        tss_ptr->tss_esp,
  327.        tss_ptr->tss_cs,
  328.        tss_ptr->tss_ds,
  329.        tss_ptr->tss_es,
  330.        tss_ptr->tss_fs,
  331.        tss_ptr->tss_gs,
  332.        tss_ptr->tss_ss,
  333.        tss_ptr->tss_cr2);
  334.     show_call_frame();
  335.   }
  336.   exit(exit_code);
  337. }
  338.  
  339. int ctrl_c_flag = 0;
  340.  
  341. void interrupt ctrl_break_func(void)
  342. {
  343.   ctrl_break_hit = 1;
  344.   tss_ptr->tss_irqn = hard_master_lo + 1;
  345.   if (!in_hardware_interrupt)
  346.     old_ctrlbrk();
  347. }
  348.  
  349. int ctrlbrk_func(void)
  350. {
  351.   tss_ptr->tss_irqn = hard_master_lo + 1;
  352.   do_faulting_finish_message(1,3);
  353.   return 0;
  354. }
  355.  
  356. char *char2rtype(word8 r, word8 relnum)
  357. {
  358.   static char buf[20];
  359.   char *fmt = "";
  360.   switch (r)
  361.   {
  362.     case 'a': fmt = ".alpha%d"; break;
  363.     case 'b': fmt = ".beta%d"; break;
  364.     case 'f': fmt = ""; break;
  365.     case 'm': fmt = ".maint%d"; break;
  366.     case 's': fmt = ".special%d"; break;
  367.     default : fmt = ".unknown%d"; break;
  368.   }
  369.   sprintf(buf, fmt, relnum);
  370.   return buf;
  371. }
  372.  
  373. void usage(char *s)
  374. {
  375.   word32 lowest_ver = GO32_LOWEST_COMPATIBLE_VERSION;
  376.   word8 *l = (word8 *)(&lowest_ver);
  377.   use_mono = 0;
  378.   fprintf(stderr, "Lowest version I can run is %d.%02d%s\n",
  379.       l[3], l[2], char2rtype(l[1], l[0]));
  380.   if (initial_argc > 1)
  381.     fprintf(stderr, "Invalid go32 usage running %s\n", s);
  382.   fprintf(stderr, "go32.exe usage: go32 [-d {debugger}] [{program} [{options} . . . ]]\n");
  383.   fprintf(stderr, "go32.exe build time was %s\n", build_time+8);
  384.   show_memory_info = 1;
  385.   if (use_DPMI)
  386.   {
  387.     DPMImaxmeminfo inf;
  388.     DPMIprotectedMode();
  389.     DPMImaxmem(&inf);
  390.     DPMIrealMode();
  391.     if (inf.physical_mem == -1 || inf.swap_mem == -1)
  392.       fprintf(stderr, "DPMI virtual memory available: %ld Kb\n", inf.largest_block / 1024L);
  393.     else
  394.     {
  395.       fprintf(stderr, "DPMI memory available: %ld Kb\n", inf.physical_mem * 4L);
  396.       fprintf(stderr, "Swap space available: %ld Kb\n", inf.swap_mem * 4L);
  397.     }
  398.   }
  399.   else
  400.   {
  401.     valloc_init();
  402.     dalloc_init();
  403.   }
  404.   exit(1);
  405. }
  406.  
  407. static void copyright(void)
  408. {
  409.   fprintf(stderr, "go32 version %d.%d%s Copyright (C) 1993 DJ Delorie\n",
  410.       GO32_MAJOR_VERSION,
  411.       GO32_MINOR_VERSION,
  412.       char2rtype(GO32_RELEASE_TYPE_C, GO32_RELEASE_NUMBER));
  413. }
  414.  
  415. int have_80387;
  416. int use_xms=0;
  417. static word32 push32(void *ptr, int len);
  418.  
  419. void setup_idt_task(int which, int tss)
  420. {
  421.   idt[which].selector = tss*8;
  422.   idt[which].stype = 0x8500;
  423.   idt[which].offset0 = 0;
  424.   idt[which].offset1 = 0;
  425. }
  426.  
  427. static void getlongargs(int *ac, char ***av)
  428. {
  429.   char *_argcs = getenv("_argc");
  430.   int _argc, i;
  431.   char tmp[10];
  432.   char **_argv;
  433.  
  434.   if (_argcs == 0)
  435.     return;
  436.   if (*ac > 1)
  437.     return;
  438.  
  439.   _argc = atoi(_argcs);
  440.   _argv = (char **)malloc((_argc+1)*sizeof(char*));
  441.   for (i = 1; i<_argc; i++)
  442.   {
  443.     sprintf(tmp, "_argv%d", i);
  444.     _argv[i] = getenv(tmp);
  445.   }
  446.   _argv[0] = (*av)[0];
  447.   _argv[i] = 0;
  448.   *av = _argv;
  449.   *ac = _argc;
  450.   putenv("_argc=");
  451. }
  452.  
  453. void main(int argc, char **argv, char **envp)
  454. {
  455.   int i, n, emu_installed=0;
  456.   struct stat stbuf;
  457.   char *cp, *path, *emu_fn=0;
  458.   unsigned short header[3];
  459.   char *external_debugger = 0;
  460.   char *running_fname;
  461.   DPMIinfo info;
  462.   int disable_dpmi = 0;
  463.   char *argv0_to_pass;
  464.   char *argv0_to_run;
  465.   int search_for_stubinfo = 0;
  466.  
  467.   initial_argc = argc;
  468.  
  469.   fprintf(stderr, "");
  470.   fflush(stderr);
  471.   fprintf(stdout, "");
  472.   fflush(stdout);
  473.  
  474.   old_mask1 = inportb(0x21);
  475.   old_mask2 = inportb(0xa1);
  476.  
  477.   /* make calls to abort() really call my_abort() */
  478.   i = _CS;
  479.   n = (int)(abort);
  480.   pokeb(i, n, 0xe9);
  481.   poke(i, n+1, (int)(my_abort) - (n + 3));
  482.  
  483.   cp = getenv("GO32");
  484.   path = 0;
  485.   if (cp)
  486.     while (1)
  487.     {
  488.       char sw[100];
  489.       char val[100];
  490.       if (sscanf(cp, "%s%n", sw, &i) < 1)
  491.     break;
  492.       cp += i;
  493.       if (stricmp(sw, "ansi") == 0)
  494.     use_ansi = 1;
  495.       else if (stricmp(sw, "topline") == 0)
  496.     topline_info = 1;
  497.       else if (stricmp(sw, "meminfo") == 0)
  498.     show_memory_info = 1;
  499.       else if (stricmp(sw, "mono") == 0)
  500.     use_mono = 1;
  501.       else if (stricmp(sw, "2r1") == 0)
  502.     redir_2_1 = 1;
  503.       else if (stricmp(sw, "1r2") == 0)
  504.     redir_1_2 = 1;
  505.       else if (stricmp(sw, "2rm") == 0)
  506.     redir_2_mono = 1;
  507.       else if (stricmp(sw, "1rm") == 0)
  508.     redir_1_mono = 1;
  509.       else if (stricmp(sw, "glob") == 0)
  510.     globbing = 1;
  511.       else if (stricmp(sw, "noglob") == 0)
  512.     globbing = 0;
  513.       else if (stricmp(sw, "nodpmi") == 0)
  514.     disable_dpmi = 1;
  515.       else
  516.       {
  517.     val[0] = 0;
  518.     sscanf(cp, "%s%n", val, &i);
  519.     cp += i;
  520.     if (val[0] == 0)
  521.       break;
  522.       }
  523.       if (stricmp(sw, "driver") == 0)
  524.       {
  525.     if (path) free(path);
  526.     path = strdup(val);
  527.       }
  528.       else if (stricmp(sw, "dpmistack") == 0)
  529.     DPMI_STACK = (atol(val) + 0xfffL) & ~0xfffL;
  530.       else if (stricmp(sw, "tw") == 0)
  531.     gr_def_tw = atoi(val);
  532.       else if (stricmp(sw, "th") == 0)
  533.     gr_def_th = atoi(val);
  534.       else if (stricmp(sw, "gw") == 0)
  535.     gr_def_gw = atoi(val);
  536.       else if (stricmp(sw, "gh") == 0)
  537.     gr_def_gh = atoi(val);
  538.       else if (stricmp(sw, "nc") == 0)
  539.     gr_def_numcolor = atoi(val);
  540.       else if (stricmp(sw, "emu") == 0)
  541.       {
  542.     if (emu_fn) free(emu_fn);
  543.     emu_fn = strdup(val);
  544.       }
  545.     }
  546.  
  547.   if (peekb(0x40,0x49) == 7)
  548.     screen_seg = 0xb000;
  549.   if (!topline_info)
  550.     use_mono = 0;
  551.   if (use_mono)
  552.     screen_seg = 0xb000;
  553.  
  554.   if (!disable_dpmi)
  555.   {
  556.     if (initDPMI(&info))
  557.     {
  558.       hard_master_lo = info.PIC.master;
  559.       hard_slave_lo = info.PIC.slave;
  560.       setDPMIvector();
  561.       DPMIrealMode();
  562.       use_DPMI = 1;
  563.       ARENA = 0;
  564.     }
  565.   }
  566.   if (!use_DPMI)
  567.   {
  568.     if (xms_installed())
  569.       use_xms = 1;
  570.   }
  571.  
  572.   bump_file_limit();
  573.   old_video_mode = peekb(0x40, 0x49);
  574.  
  575.   if (strcmp(argv[1], "!proxy") == 0)
  576.   {
  577.     int oseg, optr, i;
  578.     int far *oargv;
  579.     char far *oargve;
  580.  
  581.     if (argc > 6)
  582.     {
  583.       word32 this_version;
  584.       static word8 tvp[4] = { GO32_RELEASE_NUMBER, GO32_RELEASE_TYPE_C, GO32_MINOR_VERSION, GO32_MAJOR_VERSION };
  585.       int stubinfo_ofs, stubinfo_seg;
  586.       int si_len = sizeof(StubInfo);
  587.       StubInfo far *stubinfo_ptr;
  588.  
  589.       sscanf(argv[5], "%x", &stubinfo_seg);
  590.       sscanf(argv[6], "%x", &stubinfo_ofs);
  591.       stubinfo_ptr = (StubInfo far *)MK_FP(stubinfo_seg, stubinfo_ofs);
  592.       if (si_len > (int)stubinfo_ptr->struct_length)
  593.     si_len = (int)stubinfo_ptr->struct_length;
  594.       movedata(stubinfo_seg, stubinfo_ofs, FP_SEG(&stub_info), FP_OFF(&stub_info), si_len);
  595.  
  596.       if (DPMI_STACK < stub_info.min_stack)
  597.     DPMI_STACK = stub_info.min_stack;
  598.  
  599.       this_version = *(word32 *)tvp;
  600.  
  601.       if (stub_info.required_go32_version[1] == 's')
  602.     if (required_go32_version_w(stub_info) != this_version)
  603.     {
  604.       copyright();
  605.       fprintf(stderr, "Error: Special version (%d.%d.special%d) of go32 required to run this program.\n",
  606.         stub_info.required_go32_version[3],
  607.         stub_info.required_go32_version[2],
  608.         stub_info.required_go32_version[0]);
  609.       exit(1);
  610.     }
  611.       if (required_go32_version_w(stub_info) > this_version)
  612.       {
  613.     copyright();
  614.     fprintf(stderr, "Error: This program requires a version of go32 (%d.%d%s) newer than this one.\n",
  615.       stub_info.required_go32_version[3],
  616.       stub_info.required_go32_version[2],
  617.       char2rtype(stub_info.required_go32_version[1], stub_info.required_go32_version[0]));
  618.     exit(1);
  619.       }
  620.       if (required_go32_version_w(stub_info) < GO32_LOWEST_COMPATIBLE_VERSION)
  621.       {
  622.     copyright();
  623.     fprintf(stderr, "Error: This program requires a version of go32 (%d.%d%s) older than this one.\n",
  624.       stub_info.required_go32_version[3],
  625.       stub_info.required_go32_version[2],
  626.       char2rtype(stub_info.required_go32_version[1], stub_info.required_go32_version[0]));
  627.     exit(1);
  628.       }
  629.       
  630.       search_for_stubinfo = 0;
  631.     }
  632.  
  633.     sscanf(argv[2], "%x", &argc);
  634.     sscanf(argv[3], "%x", &oseg);
  635.     sscanf(argv[4], "%x", &optr);
  636.     oargv = MK_FP(oseg, optr);
  637.     argv = (char **)malloc(sizeof(char *) * (argc+1));
  638.     for (i=0; i<argc+1; i++)
  639.     {
  640.       if (oargv[i] == 0)
  641.       {
  642.     argv[i] = 0;
  643.     break;
  644.       }
  645.       oargve = MK_FP(oseg, oargv[i]);
  646.       for (optr=0; oargve[optr]; optr++);
  647.       argv[i] = (char *)malloc(optr+1);
  648.       for (optr=0; oargve[optr]; optr++)
  649.     argv[i][optr] = oargve[optr];
  650.       argv[i][optr] = 0;
  651.     }
  652.   }
  653.  
  654.   if (globbing == -1)
  655.     globbing = stub_info.enable_globbing;
  656.  
  657.   getlongargs(&argc, &argv);
  658.  
  659.   if (!use_DPMI)
  660.   {
  661.     ems_handle = emm_present();
  662.     switch (cputype())
  663.     {
  664.       case 1:
  665.     if ((ems_handle)&&(ems_handle != -1))
  666.       ems_free(ems_handle);
  667.     fprintf(stderr, "CPU must be a 386 to run this program.\n");
  668.     exit(1);
  669.       case 2:
  670.     if (ems_handle)
  671.       {
  672.       if ((vcpi_installed = vcpi_present()) != 0)
  673.         break;
  674.       else if (ems_handle != -1)
  675.         ems_free(ems_handle);
  676.       }
  677.     fprintf(stderr, "CPU must be in REAL mode (not V86 mode) to run this program without VCPI.\n");
  678.     fprintf(stderr, "(If you are using an EMS emulator, make sure that EMS isn't disabled)\n");
  679.     exit(1);
  680.     }
  681.   }
  682.  
  683.   _fmode = O_BINARY;
  684.   setup_graphics_driver(path);
  685.   if (path) free(path);
  686.  
  687.   setbuf(stdin, 0);
  688.   atexit((atexit_t)exit_func);
  689.   ctrlbrk(ctrlbrk_func);
  690.   old_ctrlbrk = getvect(0x1b);
  691.   setvect(0x1b, ctrl_break_func);
  692.   n = (int)ivec1-(int)ivec0;
  693.   for (i=0; i<256; i++)
  694.   {
  695.     idt[i].selector = g_altc*8;
  696.     idt[i].stype = 0x8e00;
  697.     idt[i].offset0 = (int)FP_OFF(ivec0) + n*i;
  698.     idt[i].offset1 = 0;
  699.   }
  700.   setup_idt_task(14, g_ptss);
  701.  
  702.   cp = getenv("387");
  703.   if (cp)
  704.     if (tolower(cp[0]) == 'n')
  705.       have_80387 = 0;
  706.     else if (tolower(cp[0]) == 'y')
  707.       have_80387 = 1;
  708.     else
  709.       have_80387 = detect_80387();
  710.   else
  711.     have_80387 = detect_80387();
  712.   if (have_80387)
  713.   {
  714.     idt[7].selector = g_rcode*8;
  715.     idt[7].offset0 = (int)ivec7;
  716.     idt[7].offset1 = 0;
  717.     idt[0x75].selector = g_rcode*8;
  718.     idt[0x75].offset0 = (int)ivec75;
  719.     idt[0x75].offset1 = 0;
  720.   }
  721.  
  722.   if (cp && (tolower(cp[0]) == 'q'))
  723.     if (have_80387)
  724.       printf("An 80387 has been detected.\n");
  725.     else
  726.       printf("No 80387 has been detected.\n");
  727.  
  728.   fillgdt(g_zero, 0, 0, 0, 0);
  729.   fillgdt(g_gdt, sizeof(gdt), ptr2linear(gdt), 0x92, 0);
  730.   fillgdt(g_idt, sizeof(idt), ptr2linear(idt), 0x92, 0);
  731.   fillgdt(g_rcode, 0xffff, (word32)_CS*16L, 0x9a, 0);
  732.   fillgdt(g_rdata, 0xffff, (word32)_DS*16L, 0x92, 0);
  733.   fillgdt(g_core, 0xffffffffL, 0, 0x92, 3);
  734.   fillgdt(g_acode, 0xefffffffL, 0x10000000L, 0x9a, 3);
  735.   fillgdt(g_adata, 0xefffffffL, 0x10000000L, 0x92, 3);
  736.   fillgdt(g_ctss, sizeof(TSS), ptr2linear(&c_tss), 0x89, 1);
  737.   fillgdt(g_atss, sizeof(TSS), ptr2linear(&a_tss), 0x89, 1);
  738.   fillgdt(g_ptss, sizeof(TSS), ptr2linear(&p_tss), 0x89, 1);
  739.   fillgdt(g_itss, sizeof(TSS), ptr2linear(&i_tss), 0x89, 1);
  740.   fillgdt(g_rtss, sizeof(TSS), ptr2linear(&r_tss), 0x89, 1);
  741.   fillgdt(g_rc32, 0xffff, (word32)_CS*16L, 0x9a, 3);
  742. /* CB change: this is done in "graphics.c" now */
  743. /* here this selector is initted such that we can set up a dummy paging */
  744. /* function until the first graphics mode set */
  745. /* also set up the selector for the BIOS data segment */
  746. /* OLD:
  747.  *  fillgdt(g_grdr, 0xffff, (word32)gr_paging_segment*16L, 0x9a, 0);
  748.  */
  749.   fillgdt(g_BIOSdata, 0xffff, (word32)0x400, 0x92, 0);
  750. /* end CB change */
  751.   fillgdt(g_v74, sizeof(TSS), ptr2linear(&v74_tss), 0x89, 1);
  752.   fillgdt(g_v78, sizeof(TSS), ptr2linear(&v78_tss), 0x89, 1);
  753.   fillgdt(g_v79, sizeof(TSS), ptr2linear(&v79_tss), 0x89, 1);
  754.   fillgdt(g_altc, 0xffff, ((word32)FP_SEG(ivec0))*16L, 0x9a, 0);
  755.   fillgdt(g_edcs, 0x0fffffffL, 0xa0000000L, 0x9a, 3);
  756.   fillgdt(g_edds, 0x0fffffffL, 0xa0000000L, 0x92, 3);
  757.  
  758.   setup_tss(&c_tss, go_real_mode);
  759.   setup_tss(&a_tss, go_real_mode);
  760.   setup_tss(&o_tss, go_real_mode);
  761.   setup_tss(&f_tss, go_real_mode);
  762.   setup_tss(&ed_tss, go_real_mode);
  763.   setup_tss(&r_tss, go_real_mode);
  764.   setup_tss(&i_tss, interrupt_common);
  765.   setup_tss(&p_tss, page_fault);
  766.   setup_tss(&v74_tss, v74_handler);
  767.   setup_tss(&v78_tss, v78_handler);
  768.   setup_tss(&v79_tss, v79_handler);
  769.   tss_ptr = &a_tss;
  770.  
  771.   a_tss.tss_edx = ptr2linear(&prog_info);
  772.   prog_info.size_of_this_structure_in_bytes = sizeof(PROGINFO);
  773.   prog_info.pid = 42;
  774.   transfer_linear =
  775.   prog_info.linear_address_of_transfer_buffer = ptr2linear(transfer_buffer) + 0xe0000000L;
  776.   prog_info.size_of_transfer_buffer = 4096L;
  777.   prog_info.linear_address_of_stub_info_structure = ptr2linear(&stub_info) + 0xe0000000L;
  778.   prog_info.linear_address_of_original_psp = (word32)_psp*16L + 0xe0000000L;
  779.   prog_info.run_mode = _GO32_RUN_MODE_UNDEF;
  780.   prog_info.run_mode_info = 0;
  781.  
  782.   core_selector =
  783.   a_tss.tss_gs =
  784.   prog_info.selector_for_linear_memory = (word16)(g_core * 8L);
  785.  
  786. /*  a_tss.tss_esi = 42; */ /* PID */
  787.   if(use_DPMI)
  788.   {
  789.     a_tss.tss_edi = 0;
  790.     prog_info.run_mode = _GO32_RUN_MODE_DPMI;
  791.     prog_info.run_mode_info = (info.version.major << 8)
  792.                             | ((info.version.minor/10) << 4)
  793.                             | (info.version.minor%10);
  794.   }
  795.   else
  796.     a_tss.tss_edi = ptr2linear(transfer_buffer) + 0xe0000000L;
  797.  
  798.   argv0_to_pass = argv[0];
  799.   for (i=0; argv0_to_pass[i]; i++)
  800.   {
  801.     if (argv0_to_pass[i] == '\\')
  802.       argv0_to_pass[i] = '/';
  803.     argv0_to_pass[i] = tolower(argv0_to_pass[i]);
  804.   }
  805.  
  806.   if (topline_info)
  807.     for (i=0; i<80; i++)
  808.       poke(screen_seg, i*2, 0x0720);
  809.  
  810.   if (stub_info.actual_file_to_run[0])
  811.   {
  812.     char *cp;
  813.     argv0_to_run = (char *)malloc(strlen(argv0_to_pass) + 13);
  814.     strcpy(argv0_to_run, argv0_to_pass);
  815.     for (cp = argv0_to_run + strlen(argv0_to_run) - 1; cp > argv0_to_run; cp--)
  816.       if (cp[-1] == '/' || cp[-1] == '\\' || cp[-1] == ':')
  817.     break;
  818.     strcpy(cp, stub_info.actual_file_to_run);
  819.     if (access(argv0_to_run, 0))
  820.     {
  821.       strcat(cp, ".exe");
  822.       if (access(argv0_to_run, 0))
  823.        cp[strlen(cp)-4] = 0; /* remove the .exe */
  824.     }
  825.   }
  826.   else
  827.   {
  828.     argv0_to_run = argv0_to_pass;
  829.   }
  830.  
  831.   if (emu_fn == NULL && !have_80387)
  832.   {
  833.     char *emu_try, *last_slash;
  834.  
  835.     /* If no emu_fn specified, and no 80387 is  present, check for an
  836.      * "emu387" file in the  same directory as the extender.  If we find
  837.      * one, we will use that as the 80387 emulator.  Otherwise,
  838.      * no 80387 emulation.
  839.      */
  840.  
  841.     /* Grab the directory containing the extender and append emu387. */
  842.     last_slash = strrchr (argv0_to_run, '/');
  843.     if (last_slash != NULL)
  844.     {
  845.       int path_len = last_slash - argv0_to_run + 1;    /* Length incl. '/' */
  846.       emu_try = (char *) malloc (path_len + 7);
  847.       strncpy (emu_try, argv0_to_run, path_len);
  848.       strcpy (emu_try + path_len, "emu387");
  849.     }
  850.     else
  851.       emu_try = strdup ("emu387");
  852.  
  853.     if (!stat (emu_try, &stbuf))
  854.       emu_fn = emu_try;            /* Found it. */
  855.     else
  856.       free (emu_try);            /* Nope. */
  857.   }
  858.  
  859.  
  860.   self_contained = 0;
  861.   n = open(argv0_to_run, O_RDONLY|O_BINARY);
  862.   header[0] = 0;
  863.   read(n, header, sizeof(header));
  864.   if (header[0] == 0x5a4d)
  865.   {
  866.     word32 stub_offset;
  867.     header_offset = (long)header[2]*512L;
  868.     if (header[1])
  869.       header_offset += (long)header[1] - 512L;
  870.     lseek(n, header_offset - 4, 0);
  871.     read(n, &stub_offset, 4);
  872. /*    if (search_for_stubinfo)
  873.       get_stubinfo(stub_offset); */
  874.     header[0] = 0;
  875.     read(n, header, sizeof(header));
  876.     if (header[0] == 0x010b)
  877.       self_contained = 1;
  878.     if (header[0] == 0x014c)
  879.       self_contained = 1;
  880.   }
  881.   close(n);
  882.  
  883.   if (self_contained)
  884.   {
  885.     paging_set_file(argv0_to_run);
  886.     running_fname = argv0_to_run;
  887.     emu_installed = emu_install(emu_fn);
  888.     set_command_line(argv, envp);
  889.   }
  890.   else
  891.   {
  892.     header_offset = 0;
  893.     for (cp=argv0_to_run; *cp; cp++)
  894.     {
  895.       if (*cp == '.')
  896.     path = cp;
  897.       if (*cp == '/' || *cp == '\\')
  898.     path = 0;
  899.     }
  900.     if (path)
  901.       *path = 0;
  902.     if (stat(argv0_to_run, &stbuf)) /* not found */
  903.     {
  904.       copyright();
  905.       if (strcmp(argv[1], "-d") == 0 && argc > 2)
  906.       {
  907.         debug_mode = 1;
  908.     external_debugger = argv[2];
  909.     argv += 2;
  910.     argc -= 2;
  911.       }
  912.       if (argv[1] == 0)
  913.     usage(argv0_to_pass);
  914.       paging_set_file(argv[1]);
  915.       running_fname = argv[1];
  916.       emu_installed = emu_install(emu_fn);
  917.       set_command_line(argv+1, envp);
  918.     }
  919.     else /* found */
  920.     {
  921.       paging_set_file(argv0_to_run);
  922.       running_fname = argv0_to_run;
  923.       emu_installed = emu_install(emu_fn);
  924.       set_command_line(argv, envp);
  925.     }
  926.   }
  927.  
  928.   dalloc_init();
  929.   init_controllers();
  930.  
  931.   setup_idt_task(0x74, g_v74);
  932.   setup_idt_task(hard_master_lo, g_v78);
  933.   setup_idt_task(hard_master_lo+1, g_v79);
  934.  
  935.   if(!use_DPMI)
  936.     a_tss.tss_eax = (g_core*8L)<<16;
  937.   a_tss.tss_eax |= (word32)hard_master_lo | (((word32)hard_slave_lo)<<8);
  938.  
  939.   prog_info.master_interrupt_controller_base = (word8)hard_master_lo;
  940.   prog_info.slave_interrupt_controller_base = (word8)hard_slave_lo;
  941.  
  942.   if (external_debugger)
  943.     load_external_debugger(external_debugger, running_fname, argv0_to_pass);
  944.  
  945.   if (emu_installed)
  946.   {
  947.     push32(&(a_tss.tss_eip), 4);
  948.     a_tss.tss_eip = emu_start_ip();
  949.   }
  950.   go_til_stop();
  951.   do_faulting_finish_message(1,1);
  952. }
  953.  
  954. static word32 push32(void *ptr, int len)
  955. {
  956.   if ((a_tss.tss_esp & ~0xFFF) != ((a_tss.tss_esp-len) & ~0xFFF))
  957.   {
  958.     a_tss.tss_cr2 = a_tss.tss_esp - len + ARENA;
  959.     page_in();
  960.   }
  961.   a_tss.tss_esp -= len;
  962.   a_tss.tss_esp = a_tss.tss_esp & (~3);
  963.   memput(a_tss.tss_esp+ARENA, ptr, len);
  964.   return a_tss.tss_esp;
  965. }
  966.  
  967. static int fscan_q(FILE *f, char *buf)
  968. {
  969.   char *ibuf = buf;
  970.   int c, quote=-1, gotsome=0, addquote=0;
  971.   while ((c = fgetc(f)) != EOF)
  972.   {
  973.     if (c == '\\')
  974.     {
  975.       char c2 = fgetc(f);
  976.       if (! strchr("\"'`\\ \t\n\r", c2))
  977.     *buf++ = c;
  978.       *buf++ = c2;
  979.       addquote = 0;
  980.     }
  981.     else if (c == quote)
  982.     {
  983.       quote = -1;
  984.       if (c == '\'')
  985.     addquote = 1;
  986.     }
  987.     else if (isspace(c) && (quote==-1))
  988.     {
  989.       if (gotsome)
  990.       {
  991.     if (addquote)
  992.       *buf++ = '\'';
  993.     *buf = 0;
  994.     return 1;
  995.       }
  996.       addquote = 0;
  997.     }
  998.     else
  999.     {
  1000.       if ((quote == -1) && ((c == '"') || (c == '\'')))
  1001.       {
  1002.     quote = c;
  1003.     gotsome=1;
  1004.     if ((c == '\'') && (buf == ibuf))
  1005.       *buf++ = c;
  1006.       }
  1007.       else
  1008.       {
  1009.     *buf++ = c;
  1010.     gotsome=1;
  1011.       }
  1012.       addquote = 0;
  1013.     }
  1014.   }
  1015.   return 0;
  1016. }
  1017.  
  1018. static void glob(char *buf, void (*func)(char *))
  1019. {
  1020.   if (globbing && strpbrk(buf, "*?"))
  1021.   {
  1022.     char *dire, *cp;
  1023.     struct ffblk ff;
  1024.     int done, upcase=0;
  1025.     done = findfirst(buf, &ff, FA_RDONLY|FA_DIREC|FA_ARCH);
  1026.     if (done)
  1027.       func(buf);
  1028.     else
  1029.     {
  1030.       char nbuf[180];
  1031.       strcpy(nbuf, buf);
  1032.       for (dire=cp=nbuf; *cp; cp++)
  1033.       {
  1034.     if (strchr("/\\:", *cp))
  1035.       dire = cp + 1;
  1036.     if (isupper(*cp))
  1037.       upcase = 1;
  1038.       }
  1039.       while (!done)
  1040.       {
  1041.     strcpy(dire, ff.ff_name);
  1042.     if (!upcase)
  1043.       strlwr(dire);
  1044.     if (strcmp(dire, ".") && strcmp(dire, ".."))
  1045.       func(nbuf);
  1046.     done = findnext(&ff);
  1047.       }
  1048.     }
  1049.   }
  1050.   else
  1051.     func(buf);
  1052. }
  1053.  
  1054. static void foreach_arg(char **argv, void (*func)(char *))
  1055. {
  1056.   int i;
  1057.   FILE *f;
  1058.   char buf[180];
  1059.   for (i=0; argv[i]; i++)
  1060.   {
  1061.     if (argv[i][0] == '@')
  1062.     {
  1063.       f = fopen(argv[i]+1, "rt");
  1064.       while (fscan_q(f, buf) == 1)
  1065.       {
  1066.     if (!strcmp(buf, "\032"))
  1067.       continue;
  1068.     glob(buf, func);
  1069.       }
  1070.       fclose(f);
  1071.     }
  1072.     else
  1073.       glob(argv[i], func);
  1074.   }
  1075. }
  1076.  
  1077. static int num_actual_args;
  1078.  
  1079. static void just_incr(void)
  1080. {
  1081.   num_actual_args++;
  1082. }
  1083.  
  1084. static word32 *a;
  1085.  
  1086. void pusharg(char *ar)
  1087. {
  1088.   int s = strlen(ar);
  1089.   if ((ar[0] == '\'') && (ar[s-1] == '\''))
  1090.   {
  1091.     ar[s-1] = '\0';
  1092.     ar++;
  1093.   }
  1094.   a[num_actual_args] = push32(ar, s+1);
  1095.   num_actual_args++;
  1096. }
  1097.  
  1098. void set_command_line(char **argv, char **envv)
  1099. {
  1100.   unsigned envc;
  1101.   word32 *e, v, argp, envp;
  1102.  
  1103.   a_tss.tss_cr2 = a_tss.tss_esp + ARENA;
  1104.   page_in();
  1105.  
  1106.   num_actual_args = 0;
  1107.   foreach_arg(argv, (void (*)(char*))just_incr);
  1108.  
  1109.   for (envc=0; envv[envc]; envc++);
  1110.   e = (word32 *)malloc((envc+1)*sizeof(word32));
  1111.   if (e == 0)
  1112.   {
  1113.     fprintf(stderr, "Fatal! no memory to copy environment\n");
  1114.     exit(1);
  1115.   }
  1116.   for (envc=0; envv[envc]; envc++)
  1117.   {
  1118.     char *sp, *dp;
  1119.     int state = 0;
  1120.     sp = dp = envv[envc];
  1121.     while (*sp)
  1122.     {
  1123.       switch (state)
  1124.       {
  1125.         case 0: /* waiting for '=' */
  1126.           if (!isspace(*sp))
  1127.             *dp++ = *sp;
  1128.           if (*sp == '=')
  1129.             state = 1;
  1130.           break;
  1131.         case 1: /* got '=' */
  1132.           if (!isspace(*sp))
  1133.           {
  1134.             *dp++ = *sp;
  1135.             state = 2;
  1136.           }
  1137.           break;
  1138.         case 2: /* in value */
  1139.           *dp++ = *sp;
  1140.           break;
  1141.       }
  1142.       sp++;
  1143.     }
  1144.     while (dp > envv[envc] && isspace(dp[-1]))
  1145.       *--dp = 0;
  1146.     v = push32(envv[envc], strlen(envv[envc])+1);
  1147.     e[envc] = v;
  1148.   }
  1149.   e[envc] = 0;
  1150.  
  1151.   a = (word32 *)malloc((num_actual_args+1)*sizeof(word32));
  1152.   if (a == 0)
  1153.   {
  1154.     fprintf(stderr, "Fatal! no memory to copy arguments\n");
  1155.     exit(1);
  1156.   }
  1157.   num_actual_args = 0;
  1158.   foreach_arg(argv, pusharg);
  1159.   a[num_actual_args] = 0;
  1160.  
  1161.   envp = push32(e, (envc+1)*sizeof(word32));
  1162.   argp = push32(a, (num_actual_args+1)*sizeof(word32));
  1163.  
  1164.   push32(&envp, sizeof(word32));
  1165.   push32(&argp, sizeof(word32));
  1166.   v = num_actual_args;
  1167.   push32(&v, sizeof(word32));
  1168. }
  1169.